// #include <bits/stdc++.h>
#include <mutex>
using namespace std;


/**
 * 成员声明
 * explicit, noexcept, const
 * 
 * @tparam T 
 */
template <class T>
class shared_ptr{
private:
    T* _ptr;
    int* _cnt;
    mutex* _mtx;

public:
    explicit shared_ptr(T* ptr = nullptr);
    ~shared_ptr();

    shared_ptr(const shared_ptr& sp);
    shared_ptr& operator=(const shared_ptr& sp);
    
    T& operator*() const noexcept {return *_ptr;};
    T* operator->() const noexcept {return _ptr;};

public:
    int use_count() const noexcept { return *_cnt;};
    T* get() const noexcept {return _ptr;};

private:
    void add_ref();
    void release();
};

// 不能带默认参数，默认参数只出现在声明处
template<class T>
shared_ptr<T>::shared_ptr(T* ptr): _ptr(ptr), _cnt(new int(1)), _mtx(new mutex) {} 

template<class T>
shared_ptr<T>::~shared_ptr(){
    release();
}

template<class T>
shared_ptr<T>::shared_ptr(const shared_ptr& sp): _ptr(sp._ptr), _mtx(sp._mtx), _cnt(sp._cnt) {
    add_ref();
}

template<class T>
shared_ptr<T>& shared_ptr<T>::operator=(const shared_ptr& sp){
    if(sp._ptr != _ptr){
        release();
        _ptr = sp._ptr;
        _cnt = sp._cnt;
        _mtx = sp._mtx;
        add_ref();
    }
    return *this;
}

template<class T>
void shared_ptr<T>::release(){
    bool flag = false;
    _mtx->lock();
    if(--(*_cnt) == 0){
        flag = true;
        delete _ptr;
        delete _cnt;
    }
    _mtx->unlock();
    if(flag) delete _mtx;
}

template<class T>
void shared_ptr<T>::add_ref(){
    _mtx->lock();
    ++(*_cnt);
    _mtx->unlock();
}
